﻿#include "ZLogger.h"
#include <QMutex>
#include <QThread>
#include <QDebug>

ZFLIB_BEGIN_NAMESPACE

// 当前时间
#define Z_CURRENT_TIME_STRING  (QDateTime::currentDateTime().toString(QStringLiteral("yyyy/MM/dd hh:mm:ss")))

QMutex ZLog::m_instance_mutex;

ZLog::ZLog(QObject *parent)
    : QObject(parent),
      m_mutex(QMutex::Recursive),
      m_log_output_level(LL_ALL_LOG)
{
}

ZLog::~ZLog()
{
    flush();
}

ZLog *ZLog::instance()
{
    if (!m_instance)
    {
        QMutexLocker locker(&m_instance_mutex);
        if (!m_instance)
        {
            m_instance = QSharedPointer<ZLog>(new ZLog);
        }
    }

    return m_instance.data();
}

void ZLog::destroyInstance()
{
    if (m_instance)
    {
        m_instance.clear();
    }
}

void ZLog::log(const ZLogMoule &module_id, const ZLogType &log_type,
              const ZLogLevel &log_level, const QString &msg_content,
              const QString &pos)
{
    QMutexLocker locker(&m_mutex);
    QThread *current_thread = QThread::currentThread();
    ThreadLogData &log_data = m_thread_msg_datas[current_thread];

    // 获取对应线程的数据
    if (!m_thread_msg_datas.contains(current_thread))
    {
        log_data.thread_id = QThread::currentThreadId();
        connect(current_thread, SIGNAL(finished()), SLOT(slotThreadFinished()));
    }

    // 追加日志
    ZLogMessage msg;
    msg.thread_id   = current_thread;
    msg.module_id   = module_id;
    msg.log_type    = log_type;
    msg.log_level   = log_level;
    msg.msg_content = msg_content;
    msg.pos         = pos;
    log_data.msgs << msg;

    // 输出
    if (!log_data.buffered) // 不缓冲
    {
        QList<ZLogMessage> tmp_list = log_data.msgs;
        log_data.msgs.clear();
        locker.unlock();

        // 输出
        emit sigLogMsg(tmp_list);
    }
}

void ZLog::setBuffered(bool buffered)
{
    // 1.获取对应线程的数据
    QThread *current_thread = QThread::currentThread();

    QMutexLocker locker(&m_mutex);
    ThreadLogData &log_data = m_thread_msg_datas[current_thread];
    log_data.buffered = buffered;
}

void ZLog::setLogOutputLevel(int level)
{
    m_log_output_level = level;
}

/**
 * @brief ZLog::flush
 *  不论当前是否是缓冲模式
 */
void ZLog::flush()
{
    // 1.获取对应线程的数据
    QThread *thread = QThread::currentThread();
    flushByThreadId(thread);
}

void ZLog::clearAll()
{
    QMutexLocker locker(&m_mutex);
    QMapIterator<QThread *, ThreadLogData> i(m_thread_msg_datas);
    while (i.hasNext())
    {
        i.next();
        clearByThreadId(i.key());
    }
}

void ZLog::flushAll()
{
    QMutexLocker locker(&m_mutex);
    QMapIterator<QThread *, ThreadLogData> i(m_thread_msg_datas);
    while (i.hasNext())
    {
        i.next();
        flushByThreadId(i.key());
    }
}

void ZLog::clearBufferedLog()
{
    // 1.获取对应线程的数据
    QThread *thread = QThread::currentThread();
    clearByThreadId(thread);
}

void ZLog::clearByThreadId(QThread *thread)
{
    QMutexLocker locker(&m_mutex);
    ThreadLogData &log_data = m_thread_msg_datas[thread];
    log_data.msgs.clear();
}

void ZLog::flushByThreadId(QThread *thread)
{
    QMutexLocker locker(&m_mutex);
    ThreadLogData &log_data = m_thread_msg_datas[thread];

    QList<ZLogMessage> tmp_list = log_data.msgs;
    log_data.msgs.clear();
    locker.unlock();

    // 输出
    emit sigLogMsg(tmp_list);
}

/**
 * @brief ZLog::slotThreadFinished
 *  线程结束时移除相关数据
 */
void ZLog::slotThreadFinished()
{
    QThread *thread = qobject_cast<QThread *>(sender());
    Q_ASSERT(thread);
    m_thread_msg_datas.remove(thread);
}

QSharedPointer<ZLog> ZLog::m_instance;

ZFLIB_END_NAMESPACE
